#include "Prop.h"

Prop::Prop(vector<string> data) {
    int index = 0;
    vec3 lengths = vec3(0.f);
    vec3 corner;
    name = data[index++];
    
    scale = vec3(1.f);
    trans = vec3(0.f);
    rotAngle = 0.f;
    rotAxis = vec3(1.f, 0.f, 0.f);
    color = vec3(0.f, 1.f, 0.f);
    
    while (index < data.size()) {
        if (data[index] == "model") {       
            modelPath = data[index + 1];
            index += 2;
        }
        else if (data[index] == "bounding_box") {
            index++;

            if (data[index] != "auto") {
                istringstream(data[index++]) >> lengths.x;
                istringstream(data[index++]) >> lengths.y;
                istringstream(data[index++]) >> lengths.z;
                isAutoBoundingBox = false;
            }
            else {
                isAutoBoundingBox = true;
                index++;
            }
        }
        else if (data[index] == "translate") {
            index++;
            istringstream(data[index++]) >> trans.x;
            istringstream(data[index++]) >> trans.y;
            istringstream(data[index++]) >> trans.z;
        }
        else if (data[index] == "scale") {
            index++;
            istringstream(data[index++]) >> scale.x;
            istringstream(data[index++]) >> scale.y;
            istringstream(data[index++]) >> scale.z;
        }
        else if (data[index] == "color") {
            index++;
            istringstream(data[index++]) >> color.x;
            istringstream(data[index++]) >> color.y;
            istringstream(data[index++]) >> color.z;
        }
        else if (data[index] == "rotate") {
            index++;
            istringstream(data[index++]) >> rotAxis.x;
            istringstream(data[index++]) >> rotAxis.y;
            istringstream(data[index++]) >> rotAxis.z;
            
            istringstream(data[index++]) >> rotAngle;
        }
        else if (data[index] == "texture") {
            index++;
            textPath = data[index++];
        }
        else {
            cout << "Unknown indentifier found: " << data[index] << endl;
            assert(1);
        }
    }
    
    glm::mat4 m1 = glm::translate(glm::mat4(1.0f), trans);
    glm::mat4 m2 = glm::rotate(m1, rotAngle, rotAxis);
    glm::vec4 product = m2 * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);

    model = new ModelRender(false);
    mask = BoundingBox(vec3(product), lengths * scale);
}

void Prop::Render(bool hitbox) {
    if (hitbox) {
        model->Translate(trans);
        model->Scale(mask.GetLengths());
        mask.SetColor(color);
        mask.Render();
    }
    else { 
        model->StackStack();
            model->SetColor(color);
            model->Translate(trans);
            model->Scale(scale);
            model->Draw(0.0f);
        model->EndStack();
    }
}

void Prop::SetModelData(RenderManager rManager) {
   mask.SetModelData(rManager);

   cout << "Setting prop for <" << modelPath << ">" << endl;

   if (modelPath != "none") {
      model->SetManager(rManager);
      model->Initialize(modelPath);

      if (isAutoBoundingBox) {
         printf("Generating Bounding box\n");
         GenerateBoundingBox();
      }
   }
   else {
      model->SetManager(rManager);
      model->Initialize("models/cube.obj");
   }
}

void Prop::GenerateBoundingBox() {
   vector<vec3> vertices = model->GetVertices();
   vec3 min = vec3(1000000.f);
   vec3 max = vec3(-1000000.f);

   for (int i = 0; i < vertices.size(); i++) {
      vec3 curr = vertices[i];

      min.x = std::min(min.x, curr.x);
      min.y = std::min(min.y, curr.y);
      min.z = std::min(min.z, curr.z);

      max.x = std::max(max.x, curr.x);
      max.y = std::max(max.y, curr.y);
      max.z = std::max(max.z, curr.z);
   } 

   min = (min * scale) + trans;
   max = (max * scale) + trans;

   printf("Min and max found: {%f %f %f} {%f %f %f}\n", min.x, min.y, min.z, max.x, max.y, max.z);

   mask.SetCorner(min);
   mask.SetLengths(max - min);
}

bool Prop::CollidesWith(Entity entity) {
    return mask.CollidesWith(entity.GetMask());
}
